Hallo Ihr alle, der freundliche Roach kommt mit einem interessanten Tutorial, dass euch helfen wird, eure Applikationen noch besser zu machen. Um Ihr OpenGL Programm besser aussehen zu lassen, kommen wir zu dem Problem Aliasing. Das sind die klobigen "Treppen" die bei diagonalen Linien neben den eigentlichen Pixeln auf dem Screen erscheinen. Z.B. Bad Mojo. Die Antwort lautet Anti-Aliasing und wird benutzt um diese "Treppen" zu glätten, um weichere Ecken für Objekte zu erzeugen. Ein Prozess, der eingesetzt wird, um Anti-Aliasing zu erreichen, wird "Multisampling" genannt. Die Idee ist, dass wir für jeden Pixel die benachbarten Pixel samplen und bestimmen, ob diese Ecke Anti-Aliased werden muss, also grundsätzlich "verschmieren" wir die Pixel selber und retuschieren somit die "Treppen".
Fullscreen Anti-Aliasing ist etwas, wo nicht-Echtzeit Renderprogramme immer im Vorteil waren. Wie dem auch sei, mit aktueller Hardware sind mit in der Lage, den selben Effekt in Echtzeit zu erreichen. Die ARB_MULTISAMPLE Extension erlaubt uns das. Grundsätzlich wird jeder Pixel mit seinem Nachbarn gesamplet, um das optimale Antialias herauszufinden und anzuwenden. Das kostet allerdings etwas und kann die Performance herunterziehen.
Vid_mem = sizeof(Front_buffer) + sizeof(Back_buffer) + num_samples * (sizeof(Front_buffer) +sizeof(ZS_buffer))
#include < windows.h> #include < gl/gl.h> #include < gl/glu.h> #include "arb_multisample.h"
// Deklarationen die wir benutzen werden #define WGL_SAMPLE_BUFFERS_ARB 0x2041 #define WGL_SAMPLES_ARB 0x2042 bool arbMultisampleSupported = false; int arbMultisampleFormat = 0;
bool WGLisExtensionSupported(const char *extension)
{
const size_t extlen = strlen(extension);
const char *supported = NULL;
// Versuche wglGetExtensionStringARB auf unseren aktuellen DC anzuwenden, wenn möglich
PROC wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtString)
supported = ((char*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC());
// wenn das fehlschlug, versuchen den Standard OpenGL Extension String
if (supported == NULL)
supported = (char*)glGetString(GL_EXTENSIONS);
// wenn das auch fehlschlug, dürfen keine Extensions unterstützt werden
if (supported == NULL)
return false;
// beginne Untersuchung am Anfang des Strings, inkrementiere um 1, bei einer falschen Übereinstimmung
for (const char* p = supported; ; p++)
{
// p ist unsere nächste mögliche Übereinstimmung
p = strstr(p, extension);
if (p == NULL)
return false; // Keine Übereinstimmung
// Stelle sicher, dass die Übereinstimmung am Anfang des Strings ist oder dass das
// vorhergehende Zeichen ein Leerzeichen ist, oder wir könnten versehentlich
// "wglFunkywglExtension" mit "wglExtension" als Übereinstimmung finden
// Stelle auch sicher, dass das nachfolgende Zeichen ein Leerzeichen oder NULL ist,
// da sonst "wglExtensionTwo" mit "wglExtension" übereinstimmen könnte
if ((p==supported || p[-1]==' ') && (p[extlen]=='\0' || p[extlen]==' '))
return true; // Übereinstimmung
}
}
bool InitMultisample(HINSTANCE hInstance,HWND hWnd,PIXELFORMATDESCRIPTOR pfd)
{
// Schaue, ob String in WGL existiert!
if (!WGLisExtensionSupported("WGL_ARB_multisample "))
{
arbMultisampleSupported=false;
return false;
}
// ermittle unser Pixel Format
PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB =
(PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB");
if (!wglChoosePixelFormatARB)
{
// Wir haben keine Unterstützung für Multisampling gefunden, setze unser Flag und beende.
arbMultisampleSupported=false;
return false;
}
// ermittle unseren aktuellen Device Kontext. Wir benötigen das, um das OpenGL Fenster zu fragen, welche Attribute wir haben
HDC hDC = GetDC(hWnd);
int pixelFormat;
bool valid;
UINT numFormats;
float fAttributes[] = {0,0};
// Diese Attribute sind die Bits, die wir in unserem Sample testen wollen
// alles ist ziemlicher Standard, das einzige worauf wir wirklich
// achten wollen, sind SAMPLE BUFFERS ARB und WGL SAMPLES
// Diese beiden werden das hauptsächliche Testen vornehmen, ob wir
// Unterstützung für Multisampling von der Hardware haben oder nicht
int iAttributes[] = { WGL_DRAW_TO_WINDOW_ARB,GL_TRUE,
WGL_SUPPORT_OPENGL_ARB,GL_TRUE,
WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB,
WGL_COLOR_BITS_ARB,24,
WGL_ALPHA_BITS_ARB,8,
WGL_DEPTH_BITS_ARB,16,
WGL_STENCIL_BITS_ARB,0,
WGL_DOUBLE_BUFFER_ARB,GL_TRUE,
WGL_SAMPLE_BUFFERS_ARB,GL_TRUE,
WGL_SAMPLES_ARB, 4 , // Überprüfe für 4x Multisampling
0,0};
// Als erstes überprüfen wir, ob wir ein Pixel Format für 4 Samples bekommen können
valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
// wenn wir True zurückgeliefert bekommen haben und unsere Anzahl an Formaten größer als 1 ist
if (valid && numFormats >= 1)
{
arbMultisampleSupported = true;
arbMultisampleFormat = pixelFormat;
return arbMultisampleSupported;
}
// Unser Pixel Format mit 4 Samples schlug fehl, teste für 2 Samples
iAttributes[19] = 2;
valid = wglChoosePixelFormatARB(hDC,iAttributes,fAttributes,1,&pixelFormat,&numFormats);
if (valid && numFormats >= 1)
{
arbMultisampleSupported = true;
arbMultisampleFormat = pixelFormat;
return arbMultisampleSupported;
}
// gebe das gültige Format zurück
return arbMultisampleSupported;
}
#include < windows.h> // Header Datei für die Windows Library #include < gl/gl.h> // Header Datei für die OpenGL32 Library #include < gl/glu.h> // Header Datei für die GLu32 Library #include "NeHeGL.h" // Header Datei für den NeHeGL Basecode // ROACH #include "ARB_MULTISAMPLE.h" BOOL DestroyWindowGL (GL_Window* window); BOOL CreateWindowGL (GL_Window* window); // ENDROACH
window->hDC = GetDC (window->hWnd); // hole ein Device Kontext für dieses Fenster
if (window->hDC == 0) // Haben wir einDevice Kontext bekommen?
{
// fehlgeschlagen
DestroyWindow (window->hWnd); // zerstöre das Fenster
window->hWnd = 0; // Nulle das Fenster Handle
return FALSE; // gebe False zurück
}
// ROACH
// Unser erster Durchlauf, Multisampling wurd noch nicht erzeugt, deshalb erzeugen wir ganz normal ein Fenster
// Wenn es unterstützt wird, dann sind wir in unserem zweiten Durchlauf
// das bedeutet, dass wir unser Pixel Format für Sampling benutzen
// deshalb setze PixelFormat stattdessen auf arbMultiSampleformat
if(!arbMultisampleSupported)
{
PixelFormat = ChoosePixelFormat (window->hDC, &pfd); // Finde ein kompatibles Pixel Format
if (PixelFormat == 0) // Haben wir ein kompatibles Format gefunden?
{
// fehlgeschlagen
ReleaseDC (window->hWnd, window->hDC); // gebe unserenDevice Kontext frei
window->hDC = 0; // Nulle den Device Kontext
DestroyWindow (window->hWnd); // zerstöre das Fenster
window->hWnd = 0; // Nulle das Fenster Handle
return FALSE; // gebe False zurück
}
}
else
{
PixelFormat = arbMultisampleFormat;
}
//ENDROACH
if (SetPixelFormat (window->hDC, PixelFormat, &pfd) == FALSE) // Versuche das Pixel Format zu setzen
{
// fehlgeschlagen
ReleaseDC (window->hWnd, window->hDC); // geben unserDevice Kontext frei
window->hDC = 0; // Nulle den Device Kontext
DestroyWindow (window->hWnd); // Zerstöre das Fenster
window->hWnd = 0; // Nulle das Fenster Handle
return FALSE; // gebe False zurück
}
// mache den Rendering Kontext zu unserem aktuellen Rendering Kontext
if (wglMakeCurrent (window->hDC, window->hRC) == FALSE)
{
// fehlgeschlagen
wglDeleteContext (window->hRC); // Lösche den Rendering Kontext
window->hRC = 0; // Nulle Rendering Kontext
ReleaseDC (window->hWnd, window->hDC); // gebe unseren Device Kontext frei
window->hDC = 0; // Nulle den Device Kontext
DestroyWindow (window->hWnd); // zerstöre das Fenster
window->hWnd = 0; // Nulle das FensterHandle
return FALSE; // gebe False zurück
}
// ROACH
// Nun, da unser Fenster erzeugt wurde, wollen wir abfragen, ob Samples verfügbar sind
// Wir rufen unser auf
// wenn wir einen gültigen Kontext zurückgeliefert bekommen, wollen wir unser aktuelles Fenster zerstören
// und ein neues mit dem Multisample Interface erzeugen.
if(!arbMultisampleSupported && CHECK_FOR_MULTISAMPLE)
{
if(InitMultisample(window->init.application->hInstance,window->hWnd,pfd))
{
DestroyWindowGL (window);
return CreateWindowGL(window);
}
}
// ENDROACH
ShowWindow (window->hWnd, SW_NORMAL); // mach das Fenster sichtbar
window->isVisible = TRUE;
glEnable(GL_MULTISAMPLE_ARB); // Render die Szene glDisable(GL_MULTISAMPLE_ARB);